/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package edu.pdx.cs.guavadata.query;

import edu.pdx.cs.guavadata.Channel;
import edu.pdx.cs.guavadata.Transform;
import edu.pdx.cs.guavadata.domain.Domain;
import java.util.ArrayList;

/**
 *
 * @author VuTran
 */
public class Except extends Operator {

    // relational algebra except operator: child1 - child2

    Operator child1;
    Operator child2;
    public String alias;

    public Operator getChild1() {
        return child1;
    }

    public void setChild1(Operator child1) {
        this.child1 = child1;
    }

    public Operator getChild2() {
        return child2;
    }

    public void setChild2(Operator child2) {
        this.child2 = child2;
    }

    public Except(Operator child1, Operator child2) {
        // Dummy check
        try {
            if (child1.exposedColumns.size() != child2.exposedColumns.size())
                throw new Exception("Column count does not match for Except operator.");
        } catch (Exception e) {
            System.err.println("ERROR: " + e.toString());
        }

        this.child1 = child1;
        this.child2 = child2;
        child1.parent = this;
        child2.parent = this;

        // Create the output schema, and validate that the arguments are unioncompatible
        this.exposedColumns = new ArrayList<String>();
        this.exposedDomains = new ArrayList<Domain>();

        try {
            for (int i = 0; i < child1.exposedColumns.size(); i++) {
                this.exposedColumns.add(child1.exposedColumns.get(i));
                if (!child1.exposedDomains.get(i).equals(child2.exposedDomains.get(i)))
                    throw new Exception("Column count does not match for Except operator.");
                this.exposedDomains.add(child1.exposedDomains.get(i));
            }
        } catch (Exception e) {
            System.err.println("ERROR: " + e.toString());
        }
    }

    public Except(Operator child1, Operator child2, String alias) {
        this(child1, child2);
        this.alias = alias;
    }

    @Override
    public SqlText visit(Provider qv) {
        return qv.transform(this);
    }

    @Override
    public void visit(Channel c, String table) {
        c.mapAliases(this, table);
    }

    @Override
    public void visit(Transform t, Command c) {
        t.expand(this, c);
    }

    @Override
    public void notifyChange(Operator old, Operator newOp) {
        if (this.child1 == old) {
            this.child1 = newOp;
            newOp.parent = this;
        }
        if (this.child2 == old) {
            this.child2 = newOp;
            newOp.parent = this;
        }
    }

    @Override
    public Operator clone() {
        return new Except(child1.clone(), child2.clone());
    }

}
